package icraf.carbon.gui.chart;

import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_FORMAT;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_HIDE_THRESHOLD;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_LABEL_ADD;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_LABEL_REMOVE;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_LEGEND_COLOR;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_SETTING_DISPLAY;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_SHOW_EMISSION;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_SHOW_LEGEND;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_SHOW_NEGATIVE_NPV;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_SHOW_POSITIVE_NPV;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_SHOW_SEQUESTRATION;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_SHOW_THRESHOLD;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_THRESHOLD;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_XSCALE;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_XSCALE_HA;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_XSCALE_TOTAL;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_YSCALE;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_YSCALE_LOG;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_YSCALE_NORMAL;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_ZOOM;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_ZOOM_FIT;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_ZOOM_HEIGHT;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_ZOOM_IN;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_ZOOM_OUT;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_ZOOM_SIZE;
import static icraf.carbon.gui.MenuFactory.MenuProperty.CHART_ZOOM_WIDTH;
import static icraf.carbon.gui.MenuFactory.MenuProperty.IMAGE_COPY;
import static icraf.carbon.gui.MenuFactory.MenuProperty.IMAGE_SAVE;
import static icraf.carbon.gui.MenuFactory.MenuProperty.PROJECT_SUMMARY_ABATEMENT_CHART;
import static icraf.carbon.gui.MenuFactory.MenuProperty.PROJECT_SUMMARY_TOTAL_EMISSION;
import static icraf.carbon.gui.MenuFactory.MenuProperty.PROJECT_SUMMARY_TOTAL_EMISSION_HA;
import icraf.carbon.core.AbacusData;
import icraf.carbon.core.CostBenefitUnit;
import icraf.carbon.core.Project;
import icraf.carbon.core.ProjectIO;
import icraf.carbon.gui.MenuFactory.MenuProperty;
import icraf.common.gui.MenuAdapter;
import icraf.common.gui.MenuGenerator;
import icraf.common.gui.MenuGenerator.IconModel;
import icraf.common.util.CommonFileFilter;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButton;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

/**
 * @author DHarja
 * 
 */
public class AbacusPanel extends JPanel {
	class ChartListener extends MouseAdapter {
		boolean isNull = true;

		@Override
		public void mouseMoved(MouseEvent e) {
			selectedBar = null;
			ArrayList<AbacusBar> barList = abacusChart.getBarList();
			for (AbacusBar b : barList) {
				// TODO: harus lebih efective.. search indexnya
				if (b.isVisible() && b.contains(e.getX(), e.getY())) {
					selectedBar = b;
					isNull = false;
					break;
				}
			}
			if (!isNull) {
				drawingPane.repaint();
			}
			if (selectedBar == null)
				isNull = true;
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			if (e.isPopupTrigger()||e.isControlDown()||e.getButton()==MouseEvent.BUTTON3) {
				Point p = e.getPoint();
				if (labeledBarList.contains(selectedBar)) {
					popMenuLabel.show((Component) e.getSource(), e.getX(),
							e.getY());
				} else if (selectedBar != null) {
					popMenuBar.show((Component) e.getSource(), e.getX(),
							e.getY());
				} else if (abacusChart.isInsideLeftBorder(p)) {
					popMenuAxisY.show((Component) e.getSource(), e.getX(),
							e.getY());
				} else if (abacusChart.isInsideBottomBorder(p)) {
					popMenuAxisX.show((Component) e.getSource(), e.getX(),
							e.getY());
				} else {
					popMenuChart.show((Component) e.getSource(), e.getX(),
							e.getY());
				}
			}
		}

	}

	/**
	 * @author DHarja a panel for drawing the label connector and bar hover
	 */
	class DrawingPanel extends JPanel {
		private static final long serialVersionUID = -6576652428222722701L;
		private float[] dash = { 5, 3 };
		private Font font = new Font("Aria", Font.PLAIN, 12);
		private FontMetrics fm = getFontMetrics(font);
		private DecimalFormat formatter = new DecimalFormat();
		private Color labelConnectorColor;
		private BasicStroke labelConnectorStroke;
		private Color labelGuideBackColor = new Color(0.5f, 0.5f, 0.5f, 0.7f);
		private Color labelGuideTextColor = Color.orange;
		private BasicStroke stroke2 = new BasicStroke(1);
		private BasicStroke strokeGuide = new BasicStroke(1,
				BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 20.0f, dash, 0.0f);

		public DrawingPanel() {
			formatter.setMaximumFractionDigits(2);
		}

		private void drawLabel(Graphics g2, String str, int x, int y) {
			g2.setColor(labelGuideBackColor);
			g2.fillRect(x - 3, y - fm.getHeight() * 3 / 4,
					fm.stringWidth(str) + 6, fm.getHeight());
			g2.setColor(labelGuideTextColor);
			g2.drawString(str, x, y);
		}

		@Override
		public void paint(Graphics g) {
			Graphics2D g2 = (Graphics2D) g;
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);
			if (selectedBar != null) {
				g2.setFont(font);
				g2.setStroke(stroke2);
				g2.setColor(colorHover);
				g2.draw(selectedBar);
				int y1 = (int) selectedBar.y;
				int y2 = (int) (selectedBar.y + selectedBar.height);
				int yb = abacusChart.getCanvasY()
						+ abacusChart.getCanvasHeight();
				int x1 = (int) selectedBar.x;
				int x2 = (int) (selectedBar.x + selectedBar.width);
				int xb = abacusChart.getCanvasX();
				g2.setStroke(strokeGuide);
				g2.drawLine(x1, y1, x1, yb);
				g2.drawLine(x2, y1, x2, yb);
				int yh = selectedBar.data.getCost(costBenefitUnit)
						* selectedBar.data.getEmission() > 0 ? y1 : y2;
				g2.drawLine(xb, yh, x1, yh);
				int wt = fm.stringWidth(selectedBar.getText());
				int xt = Math.max(5, x1 + (int) selectedBar.width / 2 - wt / 2);
				xt = xt + wt > getWidth() ? getWidth() - wt - 5 : xt;

				int yt = y1 + (int) selectedBar.height / 2;
				drawLabel(g2, selectedBar.getText(), xt, yt);

				AbacusData d = selectedBar.data;
				drawLabel(
						g2,
						formatter.format(d.getCost(costBenefitUnit)
								* Math.signum(d.getEmission())), xb + 5, yh - 5);

				double extX = abacusChart.isAreaScaleX() ? project
						.getTotalArea() : 1;
				int wte = fm.stringWidth(formatter.format(d.getEmission()));
				int xte = (int) (x1 + selectedBar.width / 2d - wte / 2d);
				drawLabel(g2, formatter.format(d.getEmission() * extX), xte, y2
						+ fm.getHeight());

				String strEB = formatter.format(selectedBar.getEmissionBase()
						* extX);
				int xteb = x1 - fm.stringWidth(strEB);
				drawLabel(g2, strEB, xteb - 5, yb - 5);

				String strEB2 = formatter
						.format((selectedBar.getEmissionBase() + Math.abs(d
								.getEmission())) * extX);
				drawLabel(g2, strEB2, x2 + 5, yb - 5);

			}

			if (labeledBarList.size() <= 0)
				return;
			g2.setStroke(labelConnectorStroke);
			g2.setColor(labelConnectorColor);
			for (AbacusBar b : labeledBarList) {
				if (!b.isVisible())
					continue;
				int x1 = (int) (b.getX() + b.getWidth() / 2);
				int y1 = (int) (b.getY() + b.getHeight() * 0.1);
				int x2 = b.getLabel().getX() + b.getLabel().getWidth() / 2;
				int y2 = b.getLabel().getY() + b.getLabel().getHeight();
				if (y2 > y1)
					y2 -= b.getLabel().getHeight();
				if (y2 > (b.getY() + b.getHeight()))
					y1 = (int) (b.getY() + b.getHeight() * 0.9);
				g2.drawLine(x1, y1, x2, y2);
			}
		}

		public void updateSetting(LineFormat labelConnectorSetting) {
			labelConnectorStroke = labelConnectorSetting.generateStroke();
			labelConnectorColor = labelConnectorSetting.lineColor;
		}

	}

	class LabelListener extends MouseAdapter {
		private Point loc;
		private int originX;
		private int originY;

		@Override
		public void mouseDragged(MouseEvent e) {
			int deltaX = e.getXOnScreen() - originX;
			int deltaY = e.getYOnScreen() - originY;

			JComponent l = (JComponent) e.getSource();
			if (l == null)
				return;
			if (l instanceof JLabel)
				l = legendPanel;
			l.setLocation(loc.x + deltaX, loc.y + deltaY);
			drawingPane.repaint();
		}

		@Override
		public void mouseEntered(MouseEvent e) {
			JComponent l = (JComponent) e.getSource();
			if (l instanceof JLabel) {
				l.setOpaque(true);
				legendPanel.repaint();
			} else if (l instanceof AbacusLabel) {
				AbacusLabel bl = (AbacusLabel) l;
				selectedBar = bl.getBar();
				drawingPane.repaint();
			}
		}

		@Override
		public void mouseExited(MouseEvent e) {
			JComponent l = (JComponent) e.getSource();
			if (l instanceof JLabel) {
				l.setOpaque(false);
				legendPanel.repaint();
			} else if (l instanceof AbacusLabel) {
				AbacusLabel bl = (AbacusLabel) l;
				selectedBar = bl.getBar();
				drawingPane.repaint();
			}
		}

		@Override
		public void mousePressed(MouseEvent e) {
			JComponent l = (JComponent) e.getSource();
			if (l instanceof JLabel)
				l = legendPanel;
			loc = l.getLocation();
			originX = e.getXOnScreen();
			originY = e.getYOnScreen();
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			if (e.getSource() instanceof AbacusLabel) {
				AbacusLabel l = (AbacusLabel) e.getSource();
				if (e.isPopupTrigger()||e.isControlDown()||e.getButton()==MouseEvent.BUTTON3) {
					popMenuLabel.show((Component) e.getSource(), e.getX(),
							e.getY());
					selectedBar = l.getBar();
				}
//			} else if (e.getSource() instanceof JLabel) {
//				JLabel l = (JLabel) e.getSource();
//				activeLegend = l;
//				if (e.isPopupTrigger())
//					popMenuLegend.show((Component) e.getSource(), e.getX(),
//							e.getY());
			}
		}
	}

	class Listener implements ComponentListener, ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			if (IMAGE_SAVE.isAction(e)) {
				saveImage();
			} else if (IMAGE_COPY.isAction(e)) {
				copy();
			} else if (CHART_SHOW_EMISSION.isAction(e)) {
				cbSequestration.setEnabled(cbEmission.isSelected());
				setThresholdLineVisible(cbEmission.isSelected()
						&& cbThreshold.isSelected());
				abacusChart.setShowEmission(cbEmission.isSelected());
			} else if (CHART_SHOW_SEQUESTRATION.isAction(e)) {
				cbEmission.setEnabled(cbSequestration.isSelected());
				abacusChart.setShowSequestration(cbSequestration.isSelected());
			} else if (CHART_SHOW_NEGATIVE_NPV.isAction(e)) {
				cbPositiveC.setEnabled(cbNegativeC.isSelected());
				abacusChart.setShowNegativeNPV(cbNegativeC.isSelected());
			} else if (CHART_SHOW_POSITIVE_NPV.isAction(e)) {
				cbNegativeC.setEnabled(cbPositiveC.isSelected());
				setThresholdLineVisible(cbPositiveC.isSelected()
						&& cbThreshold.isSelected());
				abacusChart.setShowPositiveNPV(cbPositiveC.isSelected());
			} else if (CHART_SHOW_THRESHOLD.isAction(e)) {
				setThresholdLineVisible(cbEmission.isSelected()
						&& cbPositiveC.isSelected() && cbThreshold.isSelected());
			} else if (CHART_HIDE_THRESHOLD.isAction(e)) {
				setThresholdLineVisible(false);
				cbThreshold.setSelected(false);
			} else if (CHART_SHOW_LEGEND.isAction(e)) {
				legendPanel.setVisible(cbLegend.isSelected());
			} else if (CHART_LABEL_ADD.isAction(e)) {
				addLabel();
			} else if (CHART_LABEL_REMOVE.isAction(e)) {
				removeSelectedBarLabel();
			} else if (CHART_THRESHOLD.isAction(e)) {
				String str = JOptionPane.showInputDialog(thresholdCostPanel,
						CHART_THRESHOLD.getLabel(), formatter.format(threshold));
				if (str == null)
					return;
				try {
					// double d = Double.parseDouble(str);
					double d = formatter.parse(str).doubleValue();
					setThreshold(Math.abs(d));
					thresholdCostPanel.repaint();
				} catch (Exception e1) {
					return;
				}
//			} else if (CHART_LEGEND_COLOR.isAction(e)) {
//				if (activeLegend != null) {
//					Zone z = labelZone.get(activeLegend);
//					Color c = colorZone.get(z);
//					Color cNew = JColorChooser
//							.showDialog(activeLegend, "Change Legend Color: "
//									+ activeLegend.getText(), c);
//					if (cNew != null) {
//						colorZone.put(z, cNew);
//						activeLegend.setIcon(new ColorIcon(cNew));
//						abacusChart.updateBarSize();
//					}
//				}
			} else if (CHART_FORMAT.isAction(e)) {
				showChartFormatSetting();
			} else if (CHART_SETTING_DISPLAY.isAction(e)) {
				showChartDisplaySetting();
			} else if (CHART_YSCALE_LOG.isAction(e)) {
				abacusChart.setScaleTypeY(ChartCanvas.LOG_SCALE);
				abacusChart.updateBarSize();
//				dispSetting.setUnitY(CHART_YSCALE_LOG);
			} else if (CHART_YSCALE_NORMAL.isAction(e)) {
				abacusChart.setScaleTypeY(ChartCanvas.NORMAL_SCALE);
				abacusChart.updateBarSize();
//				dispSetting.setUnitY(CHART_YSCALE_NORMAL);
			} else if (CHART_XSCALE_HA.isAction(e)) {
				abacusChart.setAreaScaleX(false);
				abacusChart.setTitleX(PROJECT_SUMMARY_TOTAL_EMISSION_HA
						.getLabel());
				abacusChart.updateBarSize();
//				dispSetting.setUnitX(CHART_XSCALE_HA);
			} else if (CHART_XSCALE_TOTAL.isAction(e)) {
				abacusChart.setAreaScaleX(true);
				abacusChart
						.setTitleX(PROJECT_SUMMARY_TOTAL_EMISSION.getLabel());
				abacusChart.updateBarSize();
//				dispSetting.setUnitX(CHART_XSCALE_TOTAL);
			} else if (CHART_ZOOM_IN.isAction(e)) {
				setZoom(1.25f);
			} else if (CHART_ZOOM_OUT.isAction(e)) {
				setZoom(0.75f);
			} else if (CHART_ZOOM.isAction(e)) {
				showZoomSetting();
			}
		}

		@Override
		public void componentHidden(ComponentEvent e) {
		}

		@Override
		public void componentMoved(ComponentEvent e) {
		}

		@Override
		public void componentResized(ComponentEvent e) {
			abacusChart.updateBarSize();
			Dimension dim = chartPane.getSize();
			abacusChart.setSize(dim);
			drawingPane.setSize(dim);
			thresholdCostPanel.updateSize();
			thresholdEmissionPanel.updateSize();
			thresholdCostPanel.repaint();
			for (AbacusBar b : labeledBarList) {
				b.getLabel().updateRelativeLocation();
			}
		}

		@Override
		public void componentShown(ComponentEvent e) {
		}

	}

	class ThresholdCostPanel extends JPanel {
		private static final long serialVersionUID = -6576652428222722701L;
		private BasicStroke dash = null;
		private int heightPix;
		private int label_height;
		private int label_width;
		private int panelHeight = 10;
		private LineLabelFormat setting;

		public int getHeightPix() {
			return heightPix;
		}

		@Override
		public void paint(Graphics g) {
			if (!abacusChart.isShowEmission())
				return;
			updateSize();
			Graphics2D g2 = (Graphics2D) g;
			g2.setStroke(dash);
			int x1 = 0;
			int y1 = panelHeight / 2;
			int x2 = abacusChart.getCanvasWidth();
			int y2 = y1;
			g2.setColor(setting.lineColor);
			g2.drawLine(x1, y1, x2, y2);
			FontMetrics fm = g2.getFontMetrics(setting.font);
			label_height = fm.getHeight();
			label_width = fm.stringWidth(getThresholdFormatted());
			thresholdEmissionPanel.repaint();
		}

		public void setFormat(LineLabelFormat setting) {
			this.setting = setting;
			dash = setting.generateStroke();
			thresholdCostLabel.setFont(setting.font);
			thresholdCostLabel.setForeground(setting.fontColor);
			thresholdCostLabel.setOpaque(true);
			Color c = new Color(1f, 1f, 0.5f, 0.8f);
			thresholdCostLabel.setBackground(c);
			thresholdCostLabel.setHorizontalAlignment(SwingConstants.CENTER);
		}

		public void updateSize() {
			int yLine = abacusChart.getPixelY(threshold);
			heightPix = yLine;
			this.setBounds(abacusChart.getCanvasX(), yLine - panelHeight / 2
					+ 1, abacusChart.getCanvasWidth(), panelHeight);
			thresholdCostLabel.setBounds(abacusChart.getCanvasX() + 5, yLine
					- label_height / 2, label_width + 6, label_height);
		}
	}

	class ThresholdEmissionPanel extends JPanel {
		private static final long serialVersionUID = -6576652428222722701L;
		private BasicStroke dash = null;
		private double emission;
		private DecimalFormat formatter = (DecimalFormat) NumberFormat
				.getNumberInstance();
		private int label_height = 10;
		private int label_width = 10;
		private int panelWidth = 10;
		private LineLabelFormat setting = new LineLabelFormat();

		public ThresholdEmissionPanel() {
			formatter.setMaximumFractionDigits(2);
		}

		@Override
		public void paint(Graphics g) {
			if (!abacusChart.isShowEmission())
				return;

			Graphics2D g2 = (Graphics2D) g;
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);

			g2.setStroke(dash);
			updateSize();

			String str = formatter.format(emission);
			thresholdEmissionLabel.setText(str);
			FontMetrics fm = g2.getFontMetrics(setting.font);
			label_height = fm.getHeight();
			label_width = fm.stringWidth(str);

			int x1 = panelWidth / 2;
			int y1 = 0;
			int x2 = x1;
			int y2 = this.getHeight();
			g2.setColor(setting.lineColor);
			g2.drawLine(x1, y1, x2, y2);
		}

		public void setFormat(LineLabelFormat setting) {
			this.setting = setting;
			dash = setting.generateStroke();

			thresholdEmissionLabel.setFont(setting.font);
			thresholdEmissionLabel.setForeground(setting.fontColor);
			thresholdEmissionLabel.setOpaque(true);
			Color c = new Color(1f, 1f, 0.5f, 0.8f);
			thresholdEmissionLabel.setBackground(c);
			thresholdEmissionLabel
					.setHorizontalAlignment(SwingConstants.CENTER);
		}

		public void updateSize() {
			emission = project.getTotalEmissionByCost(threshold,
					costBenefitUnit)
					* (abacusChart.isAreaScaleX() ? project.getTotalArea() : 1);
			int hMax = abacusChart.getCanvasHeight();
			int xLine = abacusChart.getPixelX(emission);
			this.setBounds(xLine - panelWidth / 2, abacusChart.getCanvasY(),
					panelWidth, hMax);
			thresholdEmissionLabel.setBounds(xLine - (label_width / 2) - 3,
					hMax - label_height, label_width + 6, label_height);
		}
	}

	class ThresholdListener extends MouseAdapter {
		private int originHeightPix;
		private int originY;

		@Override
		public void mouseDragged(MouseEvent e) {
			int hMax = abacusChart.isShowNegativeNPV() ? abacusChart
					.getCanvasHeight() / 2 : abacusChart.getCanvasHeight();
			int deltaY = e.getYOnScreen() - originY;
			int pix = originHeightPix + deltaY;
			if ((pix < abacusChart.getCanvasY())
					|| (pix >= (hMax + abacusChart.getCanvasY())))
				return;
			double t = abacusChart.getValueY(pix);
			setThreshold(t);
			thresholdEmissionPanel.updateSize();
		}

		@Override
		public void mousePressed(MouseEvent e) {
			ThresholdCostPanel t = (ThresholdCostPanel) e.getSource();
			originY = e.getYOnScreen();
			originHeightPix = t.getHeightPix();
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			if (e.isPopupTrigger()||e.isControlDown()||e.getButton()==MouseEvent.BUTTON3) {
				popMenuThreshold.show((Component) e.getSource(), e.getX(),
						e.getY());
			}
		}
	}

	class TransferableImage implements Transferable, ClipboardOwner {
		private Object data;
		private DataFlavor flavor;

		public TransferableImage(Object data, DataFlavor flavor) {
			this.data = data;
			this.flavor = flavor;
		}

		@Override
		public Object getTransferData(DataFlavor flavor)
				throws UnsupportedFlavorException, IOException {
			if (this.flavor.equals(flavor)) {
				return data;
			}
			return null;
		}

		@Override
		public DataFlavor[] getTransferDataFlavors() {
			return new DataFlavor[] { flavor };
		}

		@Override
		public boolean isDataFlavorSupported(DataFlavor flavor) {
			return this.flavor.equals(flavor);
		}

		@Override
		public void lostOwnership(Clipboard clipboard, Transferable contents) {
		}

	}

	private static final long serialVersionUID = 4770607244302899209L;

	private static JRadioButtonMenuItem[] createRadioButtonSubMenuItem(
			Container c, MenuAdapter headMenu, MenuAdapter piList[],
			ActionListener action) {
		JMenu hm = new JMenu(headMenu.getLabel());
		ButtonGroup group = new ButtonGroup();
		JRadioButtonMenuItem[] b = new JRadioButtonMenuItem[piList.length];
		for (int i = 0; i < piList.length; i++) {
			b[i] = MenuGenerator.createRadioButtonMenuItem(piList[i], action);
			group.add(hm.add(b[i]));
		}
		group.getElements().nextElement().setSelected(true);
		c.add(hm);
		return b;
	}

	private void showZoomSetting() {
		zoomWidthTF.setValue(chartPane.getWidth());
		zoomHeightTF.setValue(chartPane.getHeight());
		int ret = JOptionPane.showOptionDialog(this, zoomPanel,
				CHART_ZOOM.getLabel(), JOptionPane.OK_CANCEL_OPTION,
				JOptionPane.PLAIN_MESSAGE, null, null, null);
		if (ret == JOptionPane.OK_OPTION) {
			setZoom(-1);
		}
	}

	// TODO: format individual shape label dan bar!
	public static void main(String[] args) {
		Project p = null;
		try {
			p = ProjectIO
					.loadData(new FileReader(new File("c:/degi/tripa.car")));
		} catch (IOException e) {
			e.printStackTrace();
		}

		final JFrame frame = new JFrame();
		AbacusPanel mainPanel = new AbacusPanel();
		p.updateDataArray();
		mainPanel.setProject(p);
		mainPanel.updateChart();
		mainPanel.setPreferredSize(new Dimension(600, 400));

		frame.getContentPane().add(mainPanel, BorderLayout.CENTER);
		frame.pack();
		frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				frame.setVisible(true);
			}
		});

	}

	private AbacusChart abacusChart = new AbacusChart();
	private File activeFile;
//	private JLabel activeLegend;
	private JCheckBox cbEmission;
	private JToggleButton cbNegativeC;
	private JToggleButton cbPositiveC;
	private JCheckBox cbSequestration;

	private JToggleButton cbThreshold;
	private ChartFormat chartFormat = new ChartFormat();
	private ChartListener chartListener = new ChartListener();

	private JLayeredPane chartPane;
	private ChartSettingPanel chartSettingPanel;// = new
												// ChartSettingPanel(this);
	private Color colorHover = Color.orange;
//	private HashMap<Zone, Color> colorZone = new HashMap<Zone, Color>();
	private CostBenefitUnit costBenefitUnit;
	private CommonFileFilter defaultExtFile;

	private DisplaySettingPanel dispSetting;// = new DisplaySettingPanel();
	private DrawingPanel drawingPane = new DrawingPanel();
	private JFileChooser fileChooser = new JFileChooser();
	private DecimalFormat formatter = (DecimalFormat) NumberFormat
			.getNumberInstance();
	private DecimalFormat formatterThreshold = (DecimalFormat) NumberFormat
			.getNumberInstance();

	private boolean isEligibleOnly = false;
	private ArrayList<AbacusBar> labeledBarList = new ArrayList<AbacusBar>();
	private LabelListener labelListener = new LabelListener();
	private JMenuItem labelMenu;
//	private HashMap<JLabel, Zone> labelZone = new HashMap<JLabel, Zone>();
	private JPanel legendPanel;
	private Listener listener = new Listener();

	private MenuAdapter[] menuToolBar = { IMAGE_SAVE, IMAGE_COPY, null,
			CHART_ZOOM, CHART_ZOOM_IN, CHART_ZOOM_OUT, null, CHART_FORMAT,
			CHART_SETTING_DISPLAY };
	private MenuAdapter[] menuXScale = { CHART_XSCALE_HA, CHART_XSCALE_TOTAL };
	private JRadioButtonMenuItem[] menuXScaleB;
	private MenuAdapter[] menuYScale = { CHART_YSCALE_LOG, CHART_YSCALE_NORMAL };
	private JRadioButtonMenuItem[] menuYScaleB;
	private JPopupMenu popMenuAxisX = new JPopupMenu();
	private JPopupMenu popMenuAxisY = new JPopupMenu();
	private JPopupMenu popMenuBar = new JPopupMenu();
	private JPopupMenu popMenuChart = new JPopupMenu();
	private JPopupMenu popMenuLabel = new JPopupMenu();
	private JPopupMenu popMenuLegend = new JPopupMenu();
	private JPopupMenu popMenuThreshold = new JPopupMenu();
	private Project project;
	private JScrollPane scrollpane;
	private AbacusBar selectedBar;
	private double threshold = 5; // in $
	private JLabel thresholdCostLabel = new JLabel();
	private ThresholdCostPanel thresholdCostPanel = new ThresholdCostPanel();
	private JLabel thresholdEmissionLabel = new JLabel();
	private ThresholdEmissionPanel thresholdEmissionPanel = new ThresholdEmissionPanel();
	private ThresholdListener thresholdListener = new ThresholdListener();
	private JToolBar toolBar = new JToolBar();
	private JComboBox<Integer> zoomCB;
	private JRadioButton zoomFitRB;
	private JFormattedTextField zoomHeightTF;
	private JPanel zoomPanel;
	private JRadioButton zoomRB;
	private JRadioButton zoomSizeRB;

	private JFormattedTextField zoomWidthTF;
	private JToggleButton cbLegend;

	public AbacusPanel() {
		this.setOpaque(true);
		this.setBackground(Color.white);
		this.setLayout(new BorderLayout());

		formatter.setMaximumFractionDigits(6);

		ChartFormat cf = new ChartFormat();
		cf.label.corner = 10;
		cf.label.lineColor = Color.gray;
		cf.label.fillColor = new Color(250, 240, 200);

		cf.thresholdCost.lineColor = Color.red;
		float[] dash = { 5, 3 };
		cf.thresholdCost.dashPattern = dash;
		cf.thresholdEmission.lineColor = Color.red;
		cf.thresholdEmission.dashPattern = dash;

		Font f = new Font("Arial", Font.PLAIN, 14);
		cf.canvas.xAxis.font = f;
		cf.canvas.yAxis.font = f;
		cf.canvas.xAxisExtra.lineColor = Color.lightGray;
		cf.canvas.yAxisExtra.lineColor = Color.lightGray;

		ArrayList<ArrayList<Color>> cList = BarSettingPanel
				.generateColorTemplate(1);
		for (Color c : cList.get(0)) {
			ShapeFormat s = new ShapeFormat();
			s.fillColor = c;
			cf.barLegend.add(s);
		}

		this.setChartFormat(cf);
		abacusChart.setTitleX(PROJECT_SUMMARY_TOTAL_EMISSION_HA.getLabel());
		abacusChart.setTitleY(PROJECT_SUMMARY_ABATEMENT_CHART.getLabel());

		chartPane = new JLayeredPane();
		chartPane.addComponentListener(listener);

		drawingPane.setOpaque(false);
		chartPane.add(drawingPane);
		thresholdCostPanel.setOpaque(false);
		thresholdCostPanel.addMouseListener(thresholdListener);
		thresholdCostPanel.addMouseMotionListener(thresholdListener);
		thresholdCostPanel.setCursor(Cursor
				.getPredefinedCursor(Cursor.MOVE_CURSOR));
		// thresholdCostLabel.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
		chartPane.add(thresholdCostLabel);
		chartPane.add(thresholdCostPanel);

		thresholdEmissionPanel.setOpaque(false);

		chartPane.add(thresholdEmissionLabel);
		chartPane.add(thresholdEmissionPanel);

		legendPanel = abacusChart.getLegendPanel();
		legendPanel.setBorder(BorderFactory.createCompoundBorder(
				BorderFactory.createLineBorder(Color.darkGray),
				BorderFactory.createEmptyBorder(2, 4, 2, 2)));
		legendPanel.addMouseListener(labelListener);
		legendPanel.addMouseMotionListener(labelListener);
		legendPanel.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
		Color col = new Color(1, 1, 1, 0.75f);
		legendPanel.setBackground(col);
		legendPanel.setLocation(50 + abacusChart.getCanvasX(), 10);
		chartPane.add(legendPanel, new Integer(200));

		abacusChart.addMouseListener(chartListener);
		abacusChart.addMouseMotionListener(chartListener);
		chartPane.add(abacusChart);

		cbEmission = MenuGenerator.createCheckBox(
				MenuProperty.CHART_SHOW_EMISSION, listener);
		cbSequestration = MenuGenerator.createCheckBox(
				MenuProperty.CHART_SHOW_SEQUESTRATION, listener);

		cbPositiveC = MenuGenerator.createToggleButton(CHART_SHOW_POSITIVE_NPV,
				listener, false, IconModel.ICON16);
		cbNegativeC = MenuGenerator.createToggleButton(CHART_SHOW_NEGATIVE_NPV,
				listener, false, IconModel.ICON16);
		cbThreshold = MenuGenerator.createToggleButton(CHART_SHOW_THRESHOLD,
				listener, false, IconModel.ICON16);
		cbLegend = MenuGenerator.createToggleButton(CHART_SHOW_LEGEND,
				listener, false, IconModel.ICON16);

		cbEmission.setSelected(true);
		cbSequestration.setSelected(false);
		cbPositiveC.setSelected(true);
		cbNegativeC.setSelected(true);
		cbThreshold.setSelected(true);
		cbLegend.setSelected(true);

		toolBar = MenuGenerator.createMenuItem(toolBar, menuToolBar, listener);
		toolBar.addSeparator(new Dimension(30, 0));
		toolBar.add(cbEmission);
		toolBar.addSeparator(new Dimension(5, 0));
		toolBar.add(cbSequestration);
		toolBar.addSeparator(new Dimension(15, 0));
		toolBar.add(cbPositiveC);
		toolBar.add(cbNegativeC);
		toolBar.addSeparator();
		toolBar.add(cbThreshold);
		toolBar.add(cbLegend);

		scrollpane = new JScrollPane(chartPane);
		this.add(scrollpane, BorderLayout.CENTER);
		this.add(toolBar, BorderLayout.NORTH);

		JMenuItem m1 = MenuGenerator.createMenuItem(IMAGE_SAVE, listener);
		JMenuItem m2 = MenuGenerator.createMenuItem(IMAGE_COPY, listener);
		popMenuChart.add(m1);
		popMenuChart.add(m2);

		labelMenu = MenuGenerator.createMenuItem(CHART_LABEL_ADD, listener);
		popMenuBar.add(labelMenu);

		m1 = MenuGenerator.createMenuItem(CHART_LABEL_REMOVE, listener);
		popMenuLabel.add(m1);

		m1 = MenuGenerator.createMenuItem(CHART_THRESHOLD, listener);
		popMenuThreshold.add(m1);
		m1 = MenuGenerator.createMenuItem(CHART_HIDE_THRESHOLD, listener);
		popMenuThreshold.addSeparator();
		popMenuThreshold.add(m1);

		m1 = MenuGenerator.createMenuItem(CHART_LEGEND_COLOR, listener);
		popMenuLegend.add(m1);

		// m1 = MenuFactory.createRadioButtonSubMenuItem(
		// CHART_YSCALE, menuYScale, listener);
		// popMenuAxisY.add(m1);
		//
		// m1 = MenuFactory.createRadioButtonSubMenuItem(
		// CHART_XSCALE, menuXScale, listener);
		// popMenuAxisX.add(m1);

		menuYScaleB = createRadioButtonSubMenuItem(popMenuAxisY, CHART_YSCALE,
				menuYScale, listener);
		menuXScaleB = createRadioButtonSubMenuItem(popMenuAxisX, CHART_XSCALE,
				menuXScale, listener);

		defaultExtFile = new CommonFileFilter(" PNG File (*.png)", "png");
		fileChooser.addChoosableFileFilter(defaultExtFile);
		CommonFileFilter ext = new CommonFileFilter("JPG File (*.jpg)", "jpg");
		fileChooser.addChoosableFileFilter(ext);
		ext = new CommonFileFilter("GIF File (*.gif)", "gif");
		fileChooser.addChoosableFileFilter(ext);
		ext = new CommonFileFilter("BMP File (*.bmp)", "bmp");
		fileChooser.addChoosableFileFilter(ext);
		fileChooser.setFileFilter(defaultExtFile);

		setThreshold(threshold);

		initZoomPanel();
	}

	private void addLabel() {
		if (selectedBar == null)
			return;
		if (labeledBarList.contains(selectedBar))
			return;
		AbacusLabel l = new AbacusLabel(selectedBar);
		l.addMouseMotionListener(labelListener);
		l.addMouseListener(labelListener);
		l.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
		l.setLabelFormat(chartFormat.label);
		chartPane.add(l, new Integer(chartPane.getComponentCount()));
		chartPane.validate();
		labeledBarList.add(selectedBar);
		l.setLocation(Math.max(0, (int) (selectedBar.x + selectedBar.getWidth()
				/ 2 - l.getWidth() / 2)), Math.max(0,
				(int) selectedBar.y - l.getHeight() - 10));
		l.repaint();
		selectedBar = null;
	}

	public void copy() {
		int width = chartPane.getWidth();
		int height = chartPane.getHeight();
		BufferedImage image = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_RGB);
		Graphics2D g2 = image.createGraphics();
		chartPane.paint(g2);

		TransferableImage tr = new TransferableImage(image,
				DataFlavor.imageFlavor);
		Toolkit.getDefaultToolkit().getSystemClipboard().setContents(tr, null);
	}

	public ChartFormat getChartSetting() {
		return chartFormat;
	}

	public CostBenefitUnit getCostBenefitUnit() {
		return costBenefitUnit;
	}

	public double getThreshold() {
		return threshold;
	}

	private String getThresholdFormatted() {
		if (threshold > 10) {
			formatterThreshold.setMaximumFractionDigits(0);
		} else if (threshold > 5) {
			formatterThreshold.setMaximumFractionDigits(1);
		} else if (threshold > 0.1) {
			formatterThreshold.setMaximumFractionDigits(2);
		} else if (threshold > 0.001) {
			formatterThreshold.setMaximumFractionDigits(4);
		} else {
			formatterThreshold.setMaximumFractionDigits(6);
		}
		return formatterThreshold.format(threshold);
	}

	private void initZoomPanel() {
		zoomPanel = new JPanel(new GridLayout(4, 2, 5, 5));
		ActionListener zoomListener = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if (e.getSource().equals(zoomCB)) {
					zoomRB.setSelected(true);
				}
			}
		};
		ButtonGroup bg = new ButtonGroup();
		zoomRB = MenuGenerator.createRadioButton(CHART_ZOOM, zoomListener, bg);
		zoomRB.setText(zoomRB.getText() + "(%)");
		zoomSizeRB = MenuGenerator.createRadioButton(CHART_ZOOM_SIZE,
				zoomListener, bg);
		zoomSizeRB.setText(zoomSizeRB.getText() + "(pixels)");
		zoomFitRB = MenuGenerator.createRadioButton(CHART_ZOOM_FIT,
				zoomListener, bg);
		zoomFitRB.setSelected(true);
		Integer[] zOps = { 25, 50, 75, 125, 150, 200, 400, 800 };
		zoomCB = new JComboBox<Integer>(zOps);
		zoomCB.addActionListener(zoomListener);
		zoomCB.setSelectedIndex(3);

		FocusListener fl = new FocusListener() {
			@Override
			public void focusGained(FocusEvent e) {
				zoomSizeRB.setSelected(true);
			}

			@Override
			public void focusLost(FocusEvent e) {
			}
		};
		NumberFormat sizeFormat = NumberFormat.getIntegerInstance();

		zoomWidthTF = new JFormattedTextField(sizeFormat);
		zoomWidthTF.addFocusListener(fl);
		zoomWidthTF.setValue(200);
		JPanel pw = new JPanel(new GridLayout());
		pw.add(new JLabel(CHART_ZOOM_WIDTH.getLabel()));
		pw.add(zoomWidthTF);
		zoomHeightTF = new JFormattedTextField(sizeFormat);
		zoomHeightTF.addFocusListener(fl);
		zoomHeightTF.setValue(100);
		JPanel ph = new JPanel(new GridLayout());
		ph.add(new JLabel(CHART_ZOOM_HEIGHT.getLabel()));
		ph.add(zoomHeightTF);

		zoomPanel.add(zoomRB);
		zoomPanel.add(zoomCB);
		zoomPanel.add(zoomSizeRB);
		zoomPanel.add(pw);
		zoomPanel.add(new JLabel());
		zoomPanel.add(ph);
		zoomPanel.add(zoomFitRB);
	}

	private void refreshLabel() {
		ArrayList<AbacusBar> arrTemp = new ArrayList<AbacusBar>();
		for (AbacusBar b : labeledBarList) {
			if (!abacusChart.getBarList().contains(b)) {
				arrTemp.add(b);
				AbacusLabel l = b.getLabel();
				chartPane.remove(l);
			}
		}
		labeledBarList.removeAll(arrTemp);
	}

	private void removeSelectedBarLabel() {
		if (selectedBar == null)
			return;
		AbacusLabel l = selectedBar.getLabel();
		if (l == null)
			return;
		chartPane.remove(l);
		labeledBarList.remove(selectedBar);
		selectedBar = null;
		chartPane.validate();
		chartPane.repaint();
	}

	private void saveImage() {
		if (activeFile != null) {
			fileChooser.setCurrentDirectory(activeFile);
		}
		int ret = fileChooser.showSaveDialog(this);
		if (JFileChooser.APPROVE_OPTION != ret)
			return;
		activeFile = CommonFileFilter.getValidatedFile(fileChooser,
				defaultExtFile);
		if (activeFile.exists()) {
			ret = JOptionPane.showConfirmDialog(this, "Overwrite the file?",
					"Save Project", JOptionPane.YES_NO_OPTION,
					JOptionPane.WARNING_MESSAGE);
			if (ret == JOptionPane.NO_OPTION) {
				return;
			}
		}

		int width = chartPane.getWidth();
		int height = chartPane.getHeight();
		BufferedImage image = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_RGB);
		Graphics2D g2 = image.createGraphics();

		chartPane.paint(g2);
		g2.dispose();
		String ext = CommonFileFilter.getExtension(activeFile.getName());
		try {
			ImageIO.write(image, ext, activeFile);
		} catch (IOException ioe) {
			JOptionPane.showMessageDialog(this, "Can't write to the disk",
					"Write Error", JOptionPane.ERROR_MESSAGE);
		}
	}

	public void setChartFormat(ChartFormat chartSetting) {
		this.chartFormat = chartSetting;
		drawingPane.updateSetting(chartSetting.labelConnector);
		thresholdEmissionPanel.setFormat(chartSetting.thresholdEmission);
		thresholdCostPanel.setFormat(chartSetting.thresholdCost);
		abacusChart.setCanvasSetting(chartSetting.canvas);
		abacusChart.setBarLegend(chartSetting.barLegend);
		abacusChart.setLegendFormat(chartSetting.legend);
		abacusChart.updateChartFormat();

		for (AbacusBar b : labeledBarList) {
			b.getLabel().setLabelFormat(chartSetting.label);
			b.getLabel().repaint();
		}
	}

	public void setCostBenefitUnit(CostBenefitUnit costBenefitUnit) {
		this.costBenefitUnit = costBenefitUnit;
		abacusChart.setCostBenefitUnit(costBenefitUnit);
	}

	public void setProject(Project project) {
		this.project = project;
		// TODO: set cbu disini mungkin conflict!!
		if (getCostBenefitUnit() == null)
			this.setCostBenefitUnit(project.getCostBenefitUnitList().get(0));
		//dispSetting.setProject(project);
		//updateChart();

	}

	public void setThreshold(double threshold) {
		this.threshold = threshold;
		thresholdCostLabel.setText(getThresholdFormatted());
		thresholdCostLabel.validate();
		thresholdCostPanel.repaint();
	}

	public void setThresholdLineVisible(boolean b) {
		thresholdCostLabel.setVisible(b);
		thresholdCostPanel.setVisible(b);
		thresholdEmissionLabel.setVisible(b);
		thresholdEmissionPanel.setVisible(b);
	}

	private void setZoom(float f) {
		if (chartPane.getWidth() == 200 || chartPane.getHeight() == 100)
			return;
		int w = 0, h = 0;
		if (f > 0) {
			w = (int) (chartPane.getWidth() * f);
			h = (int) (chartPane.getHeight() * f);
		} else if (zoomRB.isSelected()) {
			if (chartPane.getWidth() == 200 || chartPane.getHeight() == 100)
				return;
			float z = ((Integer) zoomCB.getSelectedItem()).floatValue() / 100f;
			w = (int) (chartPane.getWidth() * z);
			h = (int) (chartPane.getHeight() * z);

		} else if (zoomSizeRB.isSelected()) {
			w = Integer.parseInt(zoomWidthTF.getText());
			h = Integer.parseInt(zoomHeightTF.getText());
		}
		w = Math.min(6000, Math.max(200, w));
		h = Math.min(3000, Math.max(100, h));
		chartPane.setPreferredSize(new Dimension(w, h));
		chartPane.revalidate();
	}

	private void showChartDisplaySetting() {
		if(dispSetting == null) {
			dispSetting = new DisplaySettingPanel();
			dispSetting.setProject(project);
		}
		dispSetting.setEligibleOnly(isEligibleOnly);
		dispSetting.setCostBenefitUnit(costBenefitUnit);
		dispSetting.setUnitXMin(formatter.format(abacusChart.getMinX()));
		dispSetting.setUnitXMax(formatter.format(abacusChart.getMaxX()));
		dispSetting.setUnitYMin(formatter.format(abacusChart.getMinY()));
		dispSetting.setUnitYMax(formatter.format(abacusChart.getMaxY()));
		dispSetting.setThreshold(formatter.format(getThreshold()));
		dispSetting.setUnitY(abacusChart.getScaleTypeY() == AbacusChart.NORMAL_SCALE? CHART_YSCALE_NORMAL: CHART_YSCALE_LOG);
		dispSetting.setUnitX(abacusChart.isAreaScaleX()? CHART_XSCALE_TOTAL: CHART_XSCALE_HA);
		
		int opt = JOptionPane.showOptionDialog(this, dispSetting,
				CHART_SETTING_DISPLAY.getLabel(), JOptionPane.OK_CANCEL_OPTION,
				JOptionPane.PLAIN_MESSAGE, null, null, null);
		if (opt == JOptionPane.OK_OPTION) {
			this.isEligibleOnly = dispSetting.isEligibleOnly();
			setCostBenefitUnit(dispSetting.getCostBenefitUnit());
			project.updateDataArray(isEligibleOnly);
			abacusChart.setAbacusContainer(project, costBenefitUnit);

			if (dispSetting.getUnitY() == CHART_YSCALE_LOG) {
				abacusChart.setScaleTypeY(ChartCanvas.LOG_SCALE);
				menuYScaleB[0].setSelected(true);
			} else if (dispSetting.getUnitY() == CHART_YSCALE_NORMAL) {
				abacusChart.setScaleTypeY(ChartCanvas.NORMAL_SCALE);
				menuYScaleB[1].setSelected(true);
			}

			if (dispSetting.getUnitX() == CHART_XSCALE_HA) {
				abacusChart.setAreaScaleX(false);
				abacusChart.setTitleX(PROJECT_SUMMARY_TOTAL_EMISSION_HA
						.getLabel());
				menuXScaleB[0].setSelected(true);
			} else if (dispSetting.getUnitX() == CHART_XSCALE_TOTAL) {
				abacusChart.setAreaScaleX(true);
				abacusChart
						.setTitleX(PROJECT_SUMMARY_TOTAL_EMISSION.getLabel());
				menuXScaleB[1].setSelected(true);
			}

			

			try {
				double minX = formatter.parse(dispSetting.getUnitXMin())
						.doubleValue();
				double maxX = formatter.parse(dispSetting.getUnitXMax())
						.doubleValue();
				abacusChart.setRangeX(minX, maxX);
			} catch (ParseException e) {
			}

			try {
				double minY = formatter.parse(dispSetting.getUnitYMin())
						.doubleValue();
				double maxY = formatter.parse(dispSetting.getUnitYMax())
						.doubleValue();
				abacusChart.setRangeY(minY, maxY);
			} catch (ParseException e) {
			}

			try {
				double t = formatter.parse(dispSetting.getThreshold())
						.doubleValue();
				setThreshold(t);
			} catch (ParseException e) {
			}
			
			abacusChart.updateBarData();
			refreshLabel();
			this.validate();
		}
	}

	private void showChartFormatSetting() {
		if (chartSettingPanel == null) {
			chartSettingPanel = new ChartSettingPanel(this);
		}
		chartSettingPanel.setChartFormat(this.chartFormat);
		int opt = JOptionPane.showOptionDialog(this, chartSettingPanel,
				CHART_FORMAT.getLabel(), JOptionPane.OK_CANCEL_OPTION,
				JOptionPane.PLAIN_MESSAGE, null, null, null);
		if (opt == JOptionPane.OK_OPTION) {
			setChartFormat(chartSettingPanel.getChartSetting());
		}
	}

	public void updateChart() {
		project.updateDataArray(isEligibleOnly);
		abacusChart.setAbacusContainer(project, costBenefitUnit);
		abacusChart.updateBarData();
		refreshLabel();
		
	}

}
